package server;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import utils.PrintMsg;
import utils.ServerMessage;

import common.Entity;
import common.Message;

public class ServerUDPRead implements Runnable
{
	final int ByteBufferLength = 2048;
	public static Queue<Message> UDPReadBuffer;
	
	
	public ServerUDPRead()
	{
		UDPReadBuffer = new LinkedList<Message>();
	}
	public  void run()
	{
		try
		{
			int port = 9090;
			byte[] buffer = new byte[ByteBufferLength];
			
			DatagramSocket dsocket = new DatagramSocket(port);
			DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
			
			while (true)
			{
				
				
				// Wait to receive a datagram
				dsocket.receive(packet);
				String msg = new String(buffer, 0, packet.getLength());
				
				PrintMsg.PrintStatic("Recieving UDP Packet", "IP Address: " + packet.getAddress().getHostAddress() + "\n Message: "+ msg + "\n");
				
				
				Message m = new Message(msg.getBytes());
				m.setSource(new Entity(0,packet.getAddress().getHostAddress()));
				
				/*if we read an ack, remove it the message from buffer*/
				ServerMessage sm = new ServerMessage(msg.getBytes());
				if(sm.IsServerAck())
				{
					PrintMsg.PrintStatic("Recieving UDP ACK Packet", "IP Address: " + packet.getAddress().getHostAddress() + "\n Checksum: "+ sm.getChecksum() + "\n");
					synchronized(ServerUDPSend.UDPACKBuffer)
					{
						ServerUDPSend.UDPACKBuffer.remove(sm.getChecksum());
					}
				}
				else
				{
					synchronized(UDPReadBuffer)
					{
						UDPReadBuffer.add(m);
					}
					Message mACK = new Message(ServerMessage.GenerateACKChecksum(msg.getBytes()).getBytes());
					mACK.setDest(new Entity(0,packet.getAddress().getHostAddress()));
					PrintMsg.PrintStatic("Sending ACK Packet", "IP Address: " + packet.getAddress().getHostName()+"\n");
					RelayMessages.getInstance().RecieveUDP();
					synchronized(ServerUDPSend.UDPSendBuffer)
					{
						
						ServerUDPSend.UDPSendBuffer.add(mACK);
					}
				}
				// Reset the length of the packet before reusing it.
				packet.setLength(buffer.length);
			
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

}
